#include "gd32f30x.h"
#include "stdio.h"
#include "stdint.h"
#include "string.h"
#include "DevicesSoftSPI.h"


void vSoftSPI0Init(void)
{
    /* enable the GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOB);

    /* configure GPIO pin */
    gpio_init(SOFT_SPI0_CS_GPIO_Port,   GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SOFT_SPI0_CS_Pin);
    gpio_init(SOFT_SPI0_SCLK_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SOFT_SPI0_SCLK_Pin);
    gpio_init(SOFT_SPI0_MISO_GPIO_Port, GPIO_MODE_IPU,    GPIO_OSPEED_50MHZ, SOFT_SPI0_MISO_Pin);
    gpio_init(SOFT_SPI0_MOSI_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SOFT_SPI0_MOSI_Pin);

    SOFT_SPI0_CS_HIGH();
    SOFT_SPI0_SCLK_LOW();
    SOFT_SPI0_MISO_HIGH();
    SOFT_SPI0_MOSI_HIGH();
}

void vSoftSPIxWriteByte(uint8_t ucByte)
{
    uint8_t ucMask = 0x80;

    gpio_init(SOFT_SPI0_MOSI_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SOFT_SPI0_MOSI_Pin);

    for(ucMask = 0x80; ucMask; ucMask >>= 1)
    {
        SOFT_SPI0_SCLK_LOW();

        if(ucMask & ucByte)
            SOFT_SPI0_MOSI_HIGH();
        else
            SOFT_SPI0_MOSI_LOW();

        SOFT_SPI0_SCLK_HIGH();
    }

    SOFT_SPI0_SCLK_LOW();
}

uint8_t ucSoftSPIxReadByte(void)
{
    uint8_t ucMask = 0x80, ucByte = 0;

    gpio_init(SOFT_SPI0_MISO_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, SOFT_SPI0_MISO_Pin);

    SOFT_SPI0_SCLK_LOW();

    for(ucMask = 0x80; ucMask; ucMask >>= 1)
    {
        SOFT_SPI0_SCLK_HIGH();

        if(SOFT_SPI0_MISO_READ() != RESET)
            ucByte |= ucMask;

        SOFT_SPI0_SCLK_LOW();
    }

    return ucByte;
}

int8_t cSoftSPIxWriteDatas(void *pvBuff, int32_t iLength)
{
    uint8_t *pucBuffer = pvBuff, ucMask = 0x80, ucByte = 0;
    int8_t cError = 0;

    if(pvBuff == NULL)
        return -1;

    gpio_init(SOFT_SPI0_MOSI_GPIO_Port, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, SOFT_SPI0_MOSI_Pin);

    while((iLength--) > 0)
    {
        ucByte = *pucBuffer++;

        for(ucMask = 0x80; ucMask; ucMask >>= 1)
        {
            SOFT_SPI0_SCLK_LOW();

            if(ucMask & ucByte)
                SOFT_SPI0_MOSI_HIGH();
            else
                SOFT_SPI0_MOSI_LOW();

            SOFT_SPI0_SCLK_HIGH();
        }

        SOFT_SPI0_SCLK_LOW();
    }

    return cError;
}

int8_t cSoftSPIxReadDatas(void *pvBuff, int32_t iLength)
{
    uint8_t *pucBuffer = pvBuff, ucMask = 0x80, ucByte = 0;
    int8_t cError = 0;

    if(pvBuff == NULL)
        return -1;

    gpio_init(SOFT_SPI0_MISO_GPIO_Port, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, SOFT_SPI0_MISO_Pin);

    SOFT_SPI0_SCLK_LOW();

    while((iLength--) > 0)
    {
        for(ucMask = 0x80, ucByte = 0; ucMask; ucMask >>= 1)
        {
            SOFT_SPI0_SCLK_HIGH();

            if(SOFT_SPI0_MISO_READ() != RESET)
                ucByte |= ucMask;

            SOFT_SPI0_SCLK_LOW();
        }

        *pucBuffer++ = ucByte;
    }

    return cError;
}

